Skip to content

Conversation

@tamird
Copy link
Contributor

@tamird tamird commented Nov 24, 2025

Avoid dlsym when statically linking crt.

Relative to #598 this PR keeps dlsym in place when linking dynamically and avoids the dependency on a C compiler. The benefits are as before: avoiding an indirect call when linking statically.

This also contains minor cleanup in src/backends/netbsd.rs.

Running CI on any branch is more ergonomic, particularly for folks using
CI in their forks.
@tamird tamird force-pushed the dlsym-fallback-static branch from de32ca5 to 88baf82 Compare November 24, 2025 19:55
Avoid dlsym when statically linking crt.
@tamird tamird force-pushed the dlsym-fallback-static branch from 88baf82 to edca8cf Compare November 24, 2025 19:58
Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I like the proposed approach. Not only it's significantly more complex, but I am also not sure about its universality. IIUC it checks that getrandom is available on local machine, but compiled binary may be executed in a completely different environment!

Until the minimum supported Linux kernel version is bumped by Rust, I don't think we should statically link to the getrandom symbol.


on:
push:
branches: master
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes are not relevant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, they're in a separate commit with reasoning given (it's a bummer you guys insist on squashing on merge).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tamird I think this is a reasonable thing to do, but changing on which branches CI runs is tricky from a security perspective, and it deserves a dedicated PR.

@newpavlov
Copy link
Member

Also, it's better to move the NetBSD cleanup into a separate PR.

@newpavlov
Copy link
Member

And don't forget that we have getrandom_backend="linux_getrandom", if you are fine with bumping minimum supported Linux kernel version for your application.

@tamird
Copy link
Contributor Author

tamird commented Nov 24, 2025

I don't think I like the proposed approach. Not only it's significantly more complex, but I am also not sure about its universality. IIUC it checks that getrandom is available on local machine, but compiled binary may be executed in a completely different environment!

Until the minimum supported Linux kernel version is bumped by Rust, I don't think we should statically link to the getrandom symbol.

Hm. I don't think I follow you here - we're checking if getrandom is available statically on the target, i.e. if we're statically linking against MUSL then getrandom is available statically. But we still check at runtime that the target kernel allows it.

@newpavlov
Copy link
Member

newpavlov commented Nov 24, 2025

In my understanding, you check that you can link statically on your host, so your build script will happily link to glibc's getrandom (to which your application links implicitly when you compile for GNU Linux targets) and will erroneously report that static linking can be used just fine, while the resulting application could be then deployed on a system with old glibc and Linux kernel.

Even if I misunderstand something and it works correctly in all corner cases, I don't think the additional complexity is justified by the arguably very minor benefit.

static GETRANDOM_FN: lazy::LazyUsize = lazy::LazyUsize::new();

let fptr = GETRANDOM_FN.unsync_init(init);
let fptr = unsafe { mem::transmute::<usize, GetRandomFn>(fptr) };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is probably incorrect from the strict pointer provenance point of view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The provenance of the original pointer is the same as the provenance of the pointer constructed here.

@tamird
Copy link
Contributor Author

tamird commented Nov 24, 2025

In my understanding, you check that you can link statically on your host, so your build script will happily link to glibc's getrandom (to which your application links implicitly when you compile for GNU Linux targets) and will erroneously report that static linking can be used just fine, while the resulting application could be then deployed on a system with old glibc and Linux kernel.

I don't understand this. If static linking is used, what does it matter what libc is on the target that is deployed to? Yes, the kernel might not support getrandom, but that is why we still check it at runtime using is_getrandom_good.

Even if I misunderstand something and it works correctly in all corner cases, I don't think the additional complexity is justified by the arguably very minor benefit.

Well, that's insurmountable. If you are not open to persuasion, then there's nothing to discuss.

@tamird
Copy link
Contributor Author

tamird commented Nov 24, 2025

Also, it's better to move the NetBSD cleanup into a separate PR.

Moved to #759.

Copy link
Member

@josephlr josephlr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the CI changes the changes in #759 to make it easier to actually see what is changing with linux_android_with_fallback?


on:
push:
branches: master
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tamird I think this is a reasonable thing to do, but changing on which branches CI runs is tricky from a security perspective, and it deserves a dedicated PR.

@newpavlov
Copy link
Member

newpavlov commented Nov 24, 2025

I missed the crt-static part. In the build script you run the linking check only on targets which link to the C runtime statically. In that case this could probably work, but I still do not like the heaps of additional complexity, especially considering that we already statically link to getrandom on MUSL targets. I think the linux_getrandom opt-in backend is sufficient for users who want to enforce getrandom linking on non-MUSL statically linked targets (niche of the niche by itself).

So unless @josephlr has a different opinion, I think we should not use this approach.

}

if cfg!(target_feature = "crt-static") {
match std::process::Command::new(std::env::var_os("RUSTC").unwrap())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this kind of autoconf-like detection is good to introduce as autoconf-like configuration is antithetical to how Rust projects' build systems work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds dogmatic. The real thing we want is a weak symbol but rust-lang/rust#29603.

@briansmith
Copy link
Contributor

Is static linkking to libc on Android supported by Android itself? It seems like it was decided to not try to support it in Cargo: rust-lang/cargo#10765. Go project has a similar concern: golang/go#59942 (comment). It seems like maybe it can be done and is needed for some internal stuff in Android but I am not sure that an APK-packaged app can do it.

I remember we had a discussion about whether we could issue syscalls directly on Android, and we decided to defer them to bionic because Android prefers that. But if we're linking bionic statically then we'd be effectively back to issuing syscalls directly.

@tamird
Copy link
Contributor Author

tamird commented Dec 5, 2025

This PR doesn't change behavior for android, it changes behavior for linux musl.

println!("cargo:rustc-cfg=getrandom_msan");
}

if cfg!(target_feature = "crt-static") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is good to have such auto-detection at all, but especially we shouldn't do it based on only whether crt-static is enabled. If the goal is to do something specific for MUSL on Linux. then we should restrict it to that. And, we should add a comment about why we are doing this.

Though, again, I don't think we should.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further, if the goal is to just verify that getrandom() is available and linking succeeds on statically-linked MUSL on Linux, then it is already guaranteed to succeed because MUSL 1.2.3 is the minimum MUSL version since MSRV 1.71 for Linux targets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to avoid drive this based on the user's request to statically link crt rather than e.g. hardcoding musl.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to avoid drive this based on the user's request to statically link crt rather than e.g. hardcoding musl.

Why would it make sense to dynamically set rustc-cfg=has_libc_getrandom on Windows (or any other non-Linux target)?

In general, the end-user will know whether to set has_libc_getrandom or not, and they can do it in their build system. And they could implement the dynamic detection in their build system, if they are into such things.

Anyway, I think we can close this PR now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is that the user may just say "i want static linking" and expect appropriate choices to be made by her dependencies.

@briansmith
Copy link
Contributor

This PR doesn't change behavior for android, it changes behavior for linux musl.

The PR description says "Avoid dlsym when statically linking crt." But, we have:

    #[cfg(target_env = "musl")]
    let raw_ptr = {
        let fptr: GetRandomFn = libc::getrandom;
        unsafe { transmute::<GetRandomFn, *mut c_void>(fptr) }
    };

I.e. on Linux MUSL we already avoid DLSYM.

@newpavlov
Copy link
Member

Closing per the comments above.

@newpavlov newpavlov closed this Dec 10, 2025
@briansmith
Copy link
Contributor

The PR description says "Avoid dlsym when statically linking crt." But, we have:

>  #[cfg(target_env = "musl")]

Possibly the intent is to support static linking of a libc that isn't musl, bionic, glibc, or uclibc, namely LLVM-libc or whatever it is called. I will suggest a solution in a new issue.

@briansmith
Copy link
Contributor

Possibly the intent is to support static linking of a libc that isn't musl, bionic, glibc, or uclibc, namely LLVM-libc or whatever it is called. I will suggest a solution in a new issue.

Now it's issue #766.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants